<template>
  <div id="wrapper">
    <p style="font-size: 36px; font-weight: bold; color: #4b83cd;">腾讯会议</p>
    <main>
      <p style="margin-bottom: 18px;">{{loginStatus}}</p>
      <p>主题：{{meetingSubject}}</p>
      <p>会议码：{{meetingCode}}</p>
      <p>会议id：{{meetingId}}</p>
      <p>地点：{{meetingLocation}}</p>
      <p>开始时间：{{meetingBeginTime}}</p>
      <p>结束时间：{{meetingEndTime}}</p>
      <div style="margin-top: 16px;">
        <input v-model="meetingCode"/>
        <button type="button" @click="onClickBtn" style="font-size: 14px; padding: 4px;">获取会议详情</button>
      </div>
      <div style="margin-top:20px;">
        <canvas style="border: 1px solid black;" id="video-canvas" width="200" height="100"></canvas>
        <br>
        <br>
        <button type="button" @click="onClickStartRenderBtn" style="font-size: 14px; padding: 4px;">开始渲染</button>
      </div>
      <div style="margin-top:12px;">
        <table>
          <tr>
            <td><span>frameNum: {{frameNum}}</span></td>
            <td><span>SEGT: {{sumEventGapTime}} ms</span></td>
            <td>actural interval: {{lastInterval}} ms</td>
          </tr>
          <tr>
            <td><span>FLS: {{frameDrawnLastSecond}}</span></td>
            <td><span>AEGT: {{averageEventGapTime}} ms</span></td>
            <td><span>RTR: {{renderTimeRatio}}%</span></td>
            <td><span>DFR: {{drawFrameRatio}}%</span></td>
          </tr>
        </table>
      </div>
      <div style="margin-top: 16px; margin-bottom: 30px;">
        <p>FLS: Frames drawn Last Second</p>
        <p>AEGT: Average Event Gap Time, the event is from xcast</p>
        <p>SEGT: Sum of Event Gap Time, should be 1000 ms in theory</p>
        <p>RTR: Render Time Ratio, time percentage for rendering last second</p>
        <p>DFR: Draw Frame Ratio, average time percentage for draw frame in rendering procedure last second</p>
      </div>
    </main>
  </div>
</template>

<script>
export default {
  name: 'landing-page',
  components: {},
  data: () => {
    return {
      loginStatus: '未登录',
      meetingSubject: '',
      meetingCode: '427351806',
      meetingId: '',
      meetingLocation: '',
      beginTime: '',
      endTime: '',
      ipcRenderer: '',
      frameNum: 0,
      frameDrawnLastSecond: 30,
      averageEventGapTime: 34,
      sumEventGapTime: 999,
      renderTimeRatio: 19,
      drawFrameRatio: 30,
      lastInterval: 0
    }
  },
  computed: {
    meetingBeginTime: function () {
      let bt = Number(this.beginTime)
      console.log('bt:', bt)
      if (!isNaN(bt) && bt > 0) {
        return new Date(bt * 1000).toLocaleString()
      }
      return ''
    },
    meetingEndTime: function () {
      let et = Number(this.endTime)
      console.log('bt:', et)
      if (!isNaN(et) && et > 0) {
        return new Date(et * 1000).toLocaleString()
      }
      return ''
    }
  },
  methods: {
    open (link) {
      this.$electron.shell.openExternal(link)
    },
    onConnectCallback: function (flag, data) {
      console.log('login handler', '\nflag:', flag, '\ndata:', data)
      if (flag === true) {
        this.loginStatus = '(已登录)'
      }
    },
    onQueryMeetingItemRep (flag, data) {
      if (flag === false) {
        console.log('Error: flag:', flag, 'data:', data)
        return
      }

      if (data === null) {
        console.warn(name + ' ===>>> timeout.')
        return
      }

      console.log('onQueryMeetingItemRep' + ', flag:', flag, 'data:', data)

      if (data.more === null) {
        if (data.meeting_item_list.length === 1) {
          let meetingData = data.meeting_item_list[0]
          this.meetingCode = meetingData.meeting_code
          this.meetingSubject = meetingData.subject
          this.beginTime = meetingData.begin_time
          this.endTime = meetingData.end_time
          this.meetingId = meetingData.meeting_id
          this.meetingLocation = meetingData.location
        }
      } else {
        //
      }
    },
    onClickBtn (e) {
      this.preMeetingMgr.queryMeetingItemByCode(this.meetingCode)
    },
    _oldRender () {
      let extractImageData = (image) => {
        let canvas = document.createElement('canvas')
        canvas.width = image.naturalWidth
        canvas.height = image.naturalHeight

        var context = canvas.getContext('2d')
        context.drawImage(image, 0, 0)

        let retData = context.getImageData(0, 0, canvas.width, canvas.height)
        // console.log(retData)

        return retData
      }

      this.ydata = extractImageData(document.getElementById('yplane'))
      this.udata = extractImageData(document.getElementById('uplane'))
      this.vdata = extractImageData(document.getElementById('vplane'))

      console.log(this.ydata)
      console.log(this.udata)
      console.log(this.vdata)

      this.updateFrame()

      var doFPSTest = true
      if (doFPSTest) {
        let rounds = 1000
        let start = Date.now()
        for (let i = 0; i < rounds; i++) {
          this.yuvCanvas.drawFrame(this.frame)
        }
        let delta = (Date.now() - start) / 1000
        let fps = rounds / delta
        console.log(fps + 'fps')
      }
    },
    _newRender (buffer) {
      // if (buffer) return
      // console.log('  >> in _newRender')
      // console.log('buffer type:', buffer.constructor.name)
      let start = Date.now()
      let ybytes = this.ybytes
      let ubytes = this.ubytes
      let vbytes = this.vbytes
      // let [ycur, ucur, vcur] = [0, 0, 0]
      const ylen = this.videoWidth * this.videoHeight
      const uvlen = ylen / 4
      const ustop = ylen + uvlen
      const vstop = ylen + 2 * uvlen

      // let i = 0
      // for (i = 0; i < ylen; ++i) {
      //   ybytes[ycur++] = buffer[i]
      // }
      buffer.copy(ybytes, 0, 0, ylen)

      // for (i = ylen; i < ustop; ++i) {
      //   ubytes[ucur++] = buffer[i]
      // }
      buffer.copy(ubytes, 0, ylen, ustop)

      // for (i = ylen + uvlen; i < vstop; ++i) {
      //   vbytes[vcur++] = buffer[i]
      // }
      buffer.copy(vbytes, 0, ylen + uvlen, vstop)

      let copyDataTime = Date.now() - start
      // console.log('    >> copy data:', copyDataTime, 'ms')
      start = Date.now()
      this.yuvCanvas.drawFrame(this.frame)
      let drawFrameTime = Date.now() - start
      this.drawFrameTimesInRound.push(drawFrameTime)
      this.renderTimesInRound.push(copyDataTime + drawFrameTime)
      // console.log('    >> draw frame:', drawFrameTime, 'ms')
      ++this.frameDrawnAcc
      // console.log('frameDrawnAcc:', this.frameDrawnAcc)
    },
    onClickStartRenderBtn (e) {
      this.ipcRenderer.send('add-request', 34, 35)
      this.frameDrawnLastSecond = 0
      this.frameDrawnAcc = 0
      this.drawFrameTimesInRound = []
      this.renderTimesInRound = []
      this.eventGapTimesInRound = []
      let intervalStart = Date.now()
      setInterval(() => {
        let dateNow = Date.now()
        this.lastInterval = dateNow - intervalStart
        intervalStart = dateNow

        if (this.frameNum > this.maxProcessFrameCount) return

        let sum = (a, b) => a + b
        let totalEventGapTimeLastSecond = this.eventGapTimesInRound.reduce(sum, 0)
        let totalDrawFrameTimeLastSecond = this.drawFrameTimesInRound.reduce(sum, 0)
        let totalRenderTimeLastSecond = this.renderTimesInRound.reduce(sum, 0)

        this.frameDrawnLastSecond = this.frameDrawnAcc
        console.log('frame acc === events length', this.frameDrawnLastSecond === this.eventGapTimesInRound.length)
        this.sumEventGapTime = totalEventGapTimeLastSecond
        this.averageEventGapTime = totalEventGapTimeLastSecond / this.eventGapTimesInRound.length
        this.averageEventGapTime = Number.parseFloat(this.averageEventGapTime).toFixed(2)
        this.renderTimeRatio = Number.parseFloat(totalRenderTimeLastSecond * 100 / totalEventGapTimeLastSecond).toFixed(2)
        this.drawFrameRatio = Number.parseFloat(totalDrawFrameTimeLastSecond * 100 / totalRenderTimeLastSecond).toFixed(2)

        this.frameDrawnAcc = 0
        this.drawFrameTimesInRound = []
        this.renderTimesInRound = []
        this.eventGapTimesInRound = []
      }, 1000)
    },
    copyBrightnessToPlane (imageData, plane, width, height) {
      var clampedBytes = new Uint8ClampedArray(plane.bytes.buffer, plane.bytes.offset, plane.bytes.byteLength)
      for (var y = 0; y < height; y++) {
        for (var x = 0; x < width; x++) {
          clampedBytes[y * plane.stride + x] = imageData.data[y * width * 4 + x * 4]
        }
      }
    },
    updateFrame () {
      let frame = this.frame
      let format = this.format
      if (this.ydata) {
        this.copyBrightnessToPlane(this.ydata, frame.y, format.width, format.height)
      }
      if (this.udata) {
        this.copyBrightnessToPlane(this.udata, frame.u, format.chromaWidth, format.chromaHeight)
      }
      if (this.vdata) {
        this.copyBrightnessToPlane(this.vdata, frame.v, format.chromaWidth, format.chromaHeight)
      }

      this.yuvCanvas.drawFrame(frame)
    }
  },
  mounted: function () {
    let globalAppId = '1400115281'
    let weMeetSdk = window.LibWeMeet.getInstance(globalAppId)

    console.log('sdk version:', weMeetSdk.getVersion())

    this.authService = weMeetSdk.queryAuthService()
    this.preMeetingMgr = weMeetSdk.queryPreMeetingManager()

    this.authService.registerEventHandler('login', this.onConnectCallback)
    this.preMeetingMgr.registerEventHandler('query_meeting_item_list', this.onQueryMeetingItemRep)

    var userJid = 'jasonchen'
    var appId = globalAppId
    var sdkVer = '1.0.0'
    var authType = weMeetSdk.constants.AuthType.AUTH_TYPE_USER
    // var authType = weMeetSdk.constants.AuthType.AUTH_TYPE_VISITOR
    var authParam = {
      app_id: appId,
      app_uid: userJid,
      app_token: '123456',
      token_obj: {
        app_id: appId,
        device_id: '', // empty for web
        network_type: 'network_type',
        app_version: '1.0.0',
        sdk_version: sdkVer,
        auth_type: authType
      },
      auth_type: authType,
      instance_id: weMeetSdk.constants.InstanceType.INSTANCE_WEB,
      sdk_version: sdkVer
    }
    this.authService.login(authParam)

    this.ipcRenderer = require('electron').ipcRenderer
    this.ipcRenderer.on('add-reply', (event, result, frameNum, width, height) => {
      this.videoWidth = width
      this.videoHeight = height
      if (this.format === null) {
        this.format = this.YUVBuffer.format({
          width: this.videoWidth,
          height: this.videoHeight,
          chromaWidth: this.videoWidth / 2,
          chromaHeight: this.videoHeight / 2,
          // displayWidth: 2560,
          // displayHeight: 1440
          // displayWidth: 1920,
          // displayHeight: 1080
          displayWidth: this.videoWidth,
          displayHeight: this.videoHeight
        })
        console.log('this.format:', this.format)
        this.frame = this.YUVBuffer.frame(this.format)
        this.ybytes = new Uint8Array(this.frame.y.bytes.buffer)
        this.ubytes = new Uint8Array(this.frame.u.bytes.buffer)
        this.vbytes = new Uint8Array(this.frame.v.bytes.buffer)
      }

      let start = Date.now()
      if (typeof (this.lastRenderEventTime) === 'number') {
        let eventGapTime = start - this.lastRenderEventTime
        this.eventGapTimesInRound.push(eventGapTime)
        // console.log('render event time gap:', eventGapTime / 1000)
      }
      this.lastRenderEventTime = start
      // console.log('in add-reply recv frameNum:', frameNum)
      this.frameNum = frameNum
      if (frameNum > this.maxProcessFrameCount) {
        return
      }

      // let rounds = 65
      let rounds = 1
      for (let i = 0; i < rounds; ++i) {
        this._newRender(result)
      }
      // let delta = (Date.now() - start) / 1000
      // console.log('render time:', delta)
    })

    let YUVBuffer = require('yuv-buffer')
    let YUVCanvas = require('yuv-canvas')
    this.YUVBuffer = YUVBuffer
    this.YUVCanvas = YUVCanvas

    // this.videoWidth = 1920
    // this.videoHeight = 1080
    this.format = null

    this.drawFrameTimesInRound = []
    this.renderTimesInRound = []
    this.eventGapTimesInRound = []
    this.frameDrawnAcc = 0
    this.maxProcessFrameCount = 30000

    this.yuvCanvas = YUVCanvas.attach(document.getElementById('video-canvas'))
    console.log('yuvCanvas:', typeof (this.yuvCanvas), this.yuvCanvas, this.yuvCanvas.constructor.name)
  }
}
</script>

<style>
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro");

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: "Source Sans Pro", sans-serif;
}

td {
  padding-left: 1em;
  padding-right: 1em;
  padding-top: 0.5em;
  padding-bottom: 0.5em;
}

#wrapper {
  background: radial-gradient(
    ellipse at top left,
    rgba(255, 255, 255, 1) 40%,
    rgba(229, 229, 229, 0.9) 100%
  );
  height: 100vh;
  padding: 60px 80px;
  width: 100vw;
}

#logo {
  height: auto;
  margin-bottom: 20px;
  width: 420px;
}

main {
  /* display: flex;
  justify-content: space-between; */
}

main > div {
  /* flex-basis: 50%; */
}

.left-side {
  display: flex;
  flex-direction: column;
}

.welcome {
  color: #555;
  font-size: 23px;
  margin-bottom: 10px;
}

.title {
  color: #2c3e50;
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 6px;
}

.title.alt {
  font-size: 18px;
  margin-bottom: 10px;
}

.doc p {
  color: black;
  margin-bottom: 10px;
}

.doc button {
  font-size: 0.8em;
  cursor: pointer;
  outline: none;
  padding: 0.75em 2em;
  border-radius: 2em;
  display: inline-block;
  color: #fff;
  background-color: #4fc08d;
  transition: all 0.15s ease;
  box-sizing: border-box;
  border: 1px solid #4fc08d;
}

.doc button.alt {
  color: #42b983;
  background-color: transparent;
}
</style>
